package com.apress.messaging.web.socket;

import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.WebSocketMessage;
import org.springframework.web.socket.WebSocketSession;

import cn.hutool.core.lang.Console;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;

/*import po.Message;
import service.LoginService;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;*/

/**
 * Socket处理器
 */
@Component
public class MyWebSocketHandler implements WebSocketHandler {
    @Value("${customer.online}")
    private String online;
    
    @Value("${customer.offline}")
    private String offline;
	//用于保存HttpSession与WebSocketSession的映射关系
	public static final Map<String, WebSocketSession> userSocketSessionMap;
	
	static {
		userSocketSessionMap = new ConcurrentHashMap<String, WebSocketSession>();
	}
	
	/**
	 * 建立连接后,把登录用户的id写入WebSocketSession
	 */
	public void afterConnectionEstablished(WebSocketSession session)
			throws Exception {
	    
	    String uid = (String) session.getAttributes().get("uid");
		if (userSocketSessionMap.get(uid) == null) {
			userSocketSessionMap.put(uid, session);
			HashMap<String, Object> paramMap = new HashMap<>();
            paramMap.put("userName", uid);
            String result= HttpUtil.post(online, paramMap);
            Console.log(result);
		}
		Iterator<Entry<String, WebSocketSession>> it = userSocketSessionMap
                .entrySet().iterator();
        JSONObject  jsa =   new JSONObject();
        JSONArray   PFU =   new JSONArray();
        JSONArray   CSD =   new JSONArray();
        String  key =null;
        //监听上线的类型并分别发送消息
        while (it.hasNext()) {
            Entry<String, WebSocketSession> entry = it.next();
                key =   entry.getKey();
            if(key.startsWith("PFU")){
                PFU.put(key);
            }
            //如果是客服用户则封到“PFU”中
            if(key.startsWith("CSD")){
                CSD.put(key);
            }
            jsa.put("PFU", PFU);
            jsa.put("CSD", CSD);
        }
        Console.log(uid);
        if(uid!=null){
            if(uid.startsWith("CSD")){
                //如果时客服则获取当前的在线用户列表
                JSONObject res =   new JSONObject();
                JSONObject  header  =   new JSONObject();
                header.put("code", 6000);
                header.put("message", "all online user");
                res.put("header", header);
                res.put("data", jsa);
                Console.log("客服上线获取所有的在线用户列表");
                this.sendMessageToUser(uid,new TextMessage(res+""));
                Iterator<Entry<String, WebSocketSession>> mapit = userSocketSessionMap
                        .entrySet().iterator();
                while (mapit.hasNext()) {
                    
                    Entry<String, WebSocketSession> entry = mapit.next();
                        key =   entry.getKey();
                        if(key.startsWith("PFU")){
                            Console.log(key+uid);
                            //客服上线向所有用户通知
                            Console.log("客服上线向所有用户通知");
                            JSONObject resi =   new JSONObject();
                            JSONObject  headeri  =   new JSONObject();
                            headeri.put("code", 6001);
                            headeri.put("message", "customer online");
                            resi.put("header", headeri);
                            resi.put("data", CSD);
                            this.sendMessageToUser(key,new TextMessage(resi+""));
                        }
                        
                }
            }
            if(uid.startsWith("PFU")){
                JSONObject res =   new JSONObject();
                JSONObject  header  =   new JSONObject();
                header.put("code", 6001);
                header.put("message", "all customer");
                res.put("header", header);
                res.put("data", CSD);
                //如果是用户则获取当前在线客服列表
                this.sendMessageToUser(uid,new TextMessage(res+""));
                Iterator<Entry<String, WebSocketSession>> mapit = userSocketSessionMap
                        .entrySet().iterator();
                while (mapit.hasNext()) {
                    
                    Entry<String, WebSocketSession> entry = mapit.next();
                        key =   entry.getKey();
                        if(key.startsWith("CSD")){
                            Console.log(key+uid);
                            //用户上线向所有客服通知
                            Console.log("用户上线向所有客服通知");
                            JSONObject resi =   new JSONObject();
                            JSONObject  headeri  =   new JSONObject();
                            headeri.put("code", 6002);
                            headeri.put("message", "online");
                            resi.put("header", headeri);
                            resi.put("data", uid);
                            this.sendMessageToUser(key,new TextMessage(resi+""));
                        }
                        
                }
                
            }
        }
	}

	/**
	 * 消息处理，在客户端通过Websocket API发送的消息会经过这里，然后进行相应的处理
	 */
	public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception {
			if(message.getPayloadLength()==0)
				return;
			/*Message msg=new Gson().fromJson(message.getPayload().toString(),Message.class);
			msg.setDate(new Date());
			sendMessageToUser(msg.getTo(), new TextMessage(new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss").create().toJson(msg)));*/
	}

	/**
	 * 消息传输错误处理
	 */
	public void handleTransportError(WebSocketSession session,
			Throwable exception) throws Exception {
		if (session.isOpen()) {
			session.close();
		}
		Iterator<Entry<String, WebSocketSession>> it = userSocketSessionMap.entrySet().iterator();
		// 移除当前抛出异常用户的Socket会话
		while (it.hasNext()) {
			Entry<String, WebSocketSession> entry = it.next();
			if (entry.getValue().getId().equals(session.getId())) {
				userSocketSessionMap.remove(entry.getKey());
				System.out.println("Socket会话已经移除:用户ID" + entry.getKey());
				
				HashMap<String, Object> paramMap = new HashMap<>();
		        paramMap.put("userName", entry.getKey());
		        String result= HttpUtil.post(offline, paramMap);
		        Console.log(result);
                JSONObject res =   new JSONObject();
                JSONObject  header  =   new JSONObject();
                header.put("code", 6003);
                header.put("message", "offline");
                res.put("header", header);
                res.put("data", entry.getKey());
                this.broadcast(new TextMessage(res+""));
				break;
			}
		}
	}

	/**
	 * 关闭连接后
	 */
	public void afterConnectionClosed(WebSocketSession session,CloseStatus closeStatus) throws Exception {
		System.out.println("Websocket:" + session.getId() + "已经关闭");
		Iterator<Entry<String, WebSocketSession>> it = userSocketSessionMap.entrySet().iterator();
		// 移除当前用户的Socket会话
		while (it.hasNext()) {
			Entry<String, WebSocketSession> entry = it.next();
			if (entry.getValue().getId().equals(session.getId())) {
				userSocketSessionMap.remove(entry.getKey());
				System.out.println("Socket会话已经移除:用户ID" + entry.getKey());
				
				JSONObject res =   new JSONObject();
                JSONObject  header  =   new JSONObject();
                
				HashMap<String, Object> paramMap = new HashMap<>();
                paramMap.put("userName", entry.getKey());
                String result= HttpUtil.post(offline, paramMap);
                Console.log(result);
                
                JSONObject  jst  =   JSONUtil.parseObj(result);
                JSONObject  headert  =   JSONUtil.parseObj(jst.get("header"));
                if(headert.get("code").equals(1000)){
                    header.put("code", 6003);
                    header.put("message", "offline");
                    res.put("header", header);
                    res.put("data", entry.getKey());
                }else {
                    header.put("code", 6004);
                    header.put("message", "offline fail");
                    res.put("header", header);
                    res.put("data", entry.getKey());
                }
				
                
				this.broadcast(new TextMessage(res+""));
				break;
			}
		}
	}

	public boolean supportsPartialMessages() {
		return false;
	}

	/**
	 * 给所有在线用户发送消息
	 * @param message
	 * @throws IOException
	 */
	public void broadcast(final TextMessage message) throws IOException {
		Iterator<Entry<String, WebSocketSession>> it = userSocketSessionMap.entrySet().iterator();

		//多线程群发
		while (it.hasNext()) {

			final Entry<String, WebSocketSession> entry = it.next();

			if (entry.getValue().isOpen()) {
				// entry.getValue().sendMessage(message);
				new Thread(new Runnable() {

					public void run() {
						try {
							if (entry.getValue().isOpen()) {
								entry.getValue().sendMessage(message);
							}
						} catch (IOException e) {
							e.printStackTrace();
						}
					}

				}).start();
			}

		}
	}

	/**
	 * 给某个用户发送消息
	 * 
	 * @param userName
	 * @param message
	 * @throws IOException
	 */
	public void sendMessageToUser(String uid, TextMessage message) throws IOException {
		WebSocketSession session = userSocketSessionMap.get(uid);
		if (session != null && session.isOpen()) {
			session.sendMessage(message);
		}
	}

}
